Skip to content

MockUI: StatusBar split, tour mode, variable-size menu items, helper texts#17

Merged
k9ert merged 35 commits intok9ert:mainfrom
maggo83:MarcosPlaygroundBranchForIntegration
Feb 26, 2026
Merged

MockUI: StatusBar split, tour mode, variable-size menu items, helper texts#17
k9ert merged 35 commits intok9ert:mainfrom
maggo83:MarcosPlaygroundBranchForIntegration

Conversation

@maggo83
Copy link
Copy Markdown
Collaborator

@maggo83 maggo83 commented Feb 23, 2026

Summary

This PR brings several UI improvements to MockUI and a small refactor of
the device test infrastructure.

UI Changes

StatusBar → DeviceBar + WalletBar

The monolithic status_bar.py has been replaced by two focused components:

  • device_bar.py — shows device state (lock status, battery, etc.)
  • wallet_bar.py — shows active wallet context

Tour Mode

New tour/ package with a guided first-run experience:

  • ui_explainer.py — overlay component for contextual help text
  • guided_tour.py — orchestrates the step-by-step tour flow

Variable-size Menu Items

menu.py and main_menu.py updated to support menu entries of different
heights, enabling richer layouts with subtitles or icons.

Settings Menu

New settings_menu.py added to the device submenu hierarchy.

Helper Texts & i18n

  • New translation keys added to specter_ui_en.json and specter_ui_de.json
  • Menus updated with contextual help/description strings throughout

UI State Helper

New helpers/ui_state.py centralises shared UI state logic (to replaced with actual business logic of specter hw later on).

Device Test Infrastructure

Refactor of tests_device/ — all hardcoded UI strings replaced with
values loaded from the language JSON files at collection time:

  • _load_label(key, *langs) — reads from translations section
  • _load_metadata(key, *langs) — reads from _metadata section
    (used for language_name)
  • _supported_lang_codes() — auto-discovers languages by scanning
    the languages/ directory; ensure_main_menu() now works for any
    installed language without hardcoding codes
  • click_button(label) — asserts visibility then clicks
  • navigate_to_language_menu(lang) — full 3-level navigation with
    labels resolved for the active language
  • ensure_english() — detects current UI language and switches back
    to English if needed; called from _require_device so every run
    starts in a clean known state
  • LANG_EN / LANG_DE constants replace bare "en" / "de" strings
  • --no-build-flash flag to skip build+flash during iteration
  • gc.collect() before the final navigation step to reclaim heap
    accumulated from repeated JSON parsing over serial

All 3 device integration tests pass (3/3).
All 100 unit tests continue to pass.

maggo83 and others added 30 commits December 10, 2025 09:09
-Back button size increased
-Padding/Gap title to menu contents incrased
-Menu layouts harmonized
-Realigned header of "manage_wallet_menu"
- language files are stored in folder /i18n and will be detected automatically (if properly named "specter_ui_<language code>.json"
-for missing translations the SW falls back to default language
-default language = english
-all user facing strings are taken from a dictionary with translated strings
-simply a standard menu as other before
-made GenericMenu more flexible in order to generate alternative callbacks for menu elements: now also accepts callbacks directly
-Fonts were modified offline and stored in /fonts (lv SYMBOLS were also included)
-fonts are now loaded and included in mock_ui.py before instantiating NavigationController
-Made menu size appropriate so no scroll bar appears
-merged langaunge texts for "Add Wallet" menu/title
-fixed bug in "generate_seedphrase_menu" (corrected call to superclass constructor
-Made back button in interface menu same size as rest of UI
-Language menu uses BTC ciosn "check" symbol, not lvgl
…" section in main menu

No Interface enabled -> no input available to get message to sign -> disable "sign message" option
findings documented here: k9ert#5
-also added some examples where size (even adaptive to context/state) might make sense
-also grouped "manage storage" and "manage device" into single "manage settings" menu, which is also reachable via dedicated button in the device bar
-"Change Wallet" has better fitting symbol (refresh = cycles)
-Add Wallet Size is dependent on number of wallets: none -> big, else default size
-Moved "Manage Wallet" under "Wallet" section in main menu
removed rounded corners
This reverts commit b15d21e.
After split of status bar into device bar and wallet bar there is more room
- Add UIExplainer component with spotlight overlay effect
- Add GuidedTour class as central tour controller
- Tour highlights: language, lock, interfaces, battery, power, wallet bar, help icons
- Persist tour completion state in ui_state_config.json via UIState
- Add TOUR_* translations for English and German
- Tour runs automatically on first startup, can be skipped or completed
To better fit the text
-moved files according to recent changes in main
-deleted files for which main should be taken over directly
…new menu structure, eliminate hardcoded strings, improve robustness

Adapt test case structure for language changes / persistence to new menu structure in GUI

Eliminate hardcoded UI strings and language codes from device test
infrastructure by loading them from the language JSON files at test
collection time.

conftest.py:
- Add _load_metadata() to read from the "_metadata" section of language
  JSON files (language_name, language_code, etc.)
- Add _supported_lang_codes() to auto-discover available languages by
  scanning the languages/ directory — ensure_main_menu() now recognises
  the main menu in any installed language without hardcoding "en"/"de"
- Add click_button() helper: asserts label is visible then clicks
- Add navigate_to_language_menu(lang): full 3-level navigation
  (Main → Manage Settings → Manage Device → Select Language) with
  button labels resolved from JSON for the active language
- Add ensure_english(): detects current UI language and switches back
  to English if needed; called from _require_device so the test suite
  always starts in a clean known state regardless of previous run outcome
- Add --no-build-flash flag to skip build+flash (useful during iteration)
- _require_device fixture: builds firmware with ADD_LANG=de, flashes,
  polls for boot readiness (up to 30s), then calls ensure_english()
- pytest.ini: add pythonpath = ../src

test_i18n_device.py:
- All button labels loaded via _load_label() / _load_metadata()
- LANG_EN / LANG_DE constants replace bare "en" / "de" strings
- STR_MISSING / STR_UNKNOWN_KEY hardcoded with comment pointing to
  I18nManager (host import not possible due to micropython dependency
  in MockUI/__init__.py)
- Add gc.collect() before step 4 of test_language_navigation_switch_
  persistence to reclaim heap accumulated from repeated find_labels()
  JSON parsing across the now-deeper (3-level) navigation path

All 3 device tests pass (3/3).
…inding on f469

lv.msgbox does not render correctly in the MicroPython LVGL binding on the f469: when parented to None or screen_active(), the widget produces an invisible or mis-sized result that still captures all touch input, effectively freezing the UI.

The fix replaces lv.msgbox with a manually constructed ModalOverlay class (basic/modal_overlay.py) that creates a full-screen lv.obj directly on layer_top — the only layer LVGL composites unconditionally above all screen content.

UIExplainer (guided tour) is refactored to use the same ModalOverlay, removing its own duplicated layer_top setup code. Both consumers now close the modal via modal.close().
@maggo83 maggo83 force-pushed the MarcosPlaygroundBranchForIntegration branch from cee0ad5 to ad95be1 Compare February 26, 2026 14:20
@k9ert k9ert merged commit b7962d2 into k9ert:main Feb 26, 2026
1 check passed
@maggo83 maggo83 deleted the MarcosPlaygroundBranchForIntegration branch March 10, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants